;;; deno-repl-options.el
;;; Version - 1.0.0
;;; Author - Nalin Ranjan

(cl-defstruct deno-repl-options
  "deno-repl-options"
  
  (config nil
	  :type 'string
	  :documentation
	  "switch format: --config <FILE>
           Load configuration file.
           Ignored if <FILE> is nil or empty-like string")
  
  (cached-only nil
	       :type 'boolean
	       :documentation
	       "switch format: --cached-only
                Require that remote dependencies are already cached.
                Ignored if nil.")
  (cert nil
	:type 'string
	:documentation
	"switch format: --cert <FILE>
         Load certificate authority from PEM encoded file.
         Ignored if nil.")
  
  (compat nil
	  :type 'boolean
	  :documentation
	  "switch format: --compat
           Node compatibility mode. Currently only enables built-in node modules like 'fs' and globals like 'process'.
           Ignored if nil.")

  (eval nil
	:type 'string
	:documentation
	"switch format: --eval <code>
         Evaluates the provided code when the REPL starts.
         Ignored if nil.")

  ;; (eval-file) ;; gotta pull latest to get this option
  (help nil
	:type 'boolean
	:documentation
	"switch format: --help
         Print help information.
         Ignored if nil")
  
  (import-map nil
	      :type 'string
	      :documentation
	      "switch format: --import-map <FILE>
               Load import map file.
               Ignored if nil.")
  
  (inspect nil
	   :type 'list
	   :documentation "switch format: --inspect=<HOST:PORT>...
                           Activate inspector on host:port (default: 127.0.0.1:9229).
                           Ignored if nil")
  
  (inspect-brk nil
	       :type 'list
	       :documentation
	       "switch format: --inspect-brk=<HOST:PORT>...
                Activate inspector on host:port and break at start of user script.
                Ignored if nil.")

  (log-level nil
	     :type 'string
	     :documentation
	     "switch format: --log-level <log-level>
              Set log level [possible values: debug, info]
              Ignored if nil.")
  
  (location nil
	    :type 'string
	    :documentation
	    "switch format: --location <HREF>
             Value of 'globalThis.location' used by some web API(s).
             Ignored if nil.")
  
  (lock nil
	:type 'string
	:documentation
	"switch format: --lock <FILE>
         Check the specified lock file.
         Ignored if nil.")
  
  (lock-write nil
	      :type 'boolean
	      :documentation
	      "switch format: --lock-write
               Write lock file (use with --lock).
               Ignored if nil.")
  
  (no-check nil
	    :type 'list
	    :documentation
	    "switch format: --no-check=<NO_CHECK_TYPE>...
             Skip type checking modules.
             Ignored if nil.")
  
  (no-remote nil
	     :type 'boolean
	     :documentation
	     "switch format: --no-remote
              Do not resolve remote modules.
              Ignored if nil.")
  
  (quiet nil
	 :type 'boolean
	 :documentation
	 "switch format: --quiet
          Suppress diagnostic output.
          Ignored if nil.")

  (reload nil
	  :type 'list
	  :documentation
	  "switch format: --reload=<CACHE_BLOCKLIST>...
           Reload source code cache (recompile Typescript).
           Ignored if nil.")
  
  (seed nil
	:type 'number
	:documentation
	"switch format: --seed <NUMBER>
         Seed Math.random().
         Ignored if nil.")
  
  (unsafely-ignore-certificate-errors nil
				      :type 'list
				      :documentation
				      "switch format: --unsafely-ignore-certificate-errors=<HOSTNAMES>...
                                       DANGER: Disables verification of TLS certificates.
                                       Ignored if nil.")

  (unstable nil
	    :type 'boolean
	    :documentation
	    "switch format: --unstable
             Enable unstable features and API(s).
             Ignored if nil.")

  (v8-flags nil
	    :type 'list
	    :documentation
	    "switch format: --v8-flags=<v8-flags>
             Set VS command line options (for help: --vs-flags=--help).
             Ignored if nil."))

(defconst deno-cli-path "deno")

(defconst deno-cli-args (list "repl"))

(defun deno-repl-command (&optional repl-options)
  "Function to build a deno repl command"
  (let*
      ((read-boolean #'(lambda (option-value)
			 (and
			  (booleanp option-value)
			  (not (null option-value))
			  (eq option-value t))))
       
       (read-number #'(lambda (option-value)
			(and repl-options
			     (numberp option-value)
			     (number-to-string option-value))))
       
       (read-string #'(lambda (option-value)
			       (and repl-options
				    (stringp option-value)
				    (not (string= (string-trim option-value) ""))
				    (string-trim option-value))))
       (read-config #'(lambda ()
			(and repl-options
			     (let*
				 ((config (deno-repl-options-config repl-options))
				  (config-option (funcall read-string config)))
			       (and config-option (list "--config" config-option))))))

       (read-log-level #'(lambda ()
			   (and repl-options
				(let*
				    ((log-level (deno-repl-options-log-level repl-options))
				     (log-level-option (funcall read-string log-level)))
				  (and log-level-option (list "--log-level" log-level-option))))))
       
       (read-lock #'(lambda ()
		      (and repl-options
			   (let*
			       ((lock (deno-repl-options-lock repl-options))
				(lock-option (funcall read-string lock)))
			     (and lock-option (list "--lock" lock-option))))))
       
       (read-cert #'(lambda ()
		      (and repl-options
			   (let*
			       ((cert (deno-repl-options-cert repl-options))
				(cert-option (funcall read-string cert)))
			     (and cert-option (list "--cert" cert-option))))))

       (read-eval #'(lambda ()
		      (and repl-options
			   (let*
			       ((eval (deno-repl-options-eval repl-options))
				(eval-option (funcall read-string eval)))
			     (and eval-option (list "--eval" (string-join (list "\"" eval-option "\"") "")))))))

       (read-import-map #'(lambda ()
			    (and repl-options
				 (let*
				     ((import-map (deno-repl-options-import-map repl-options))
				      (import-map-option (funcall read-string import-map)))
				   (and import-map-option (list "--import-map" import-map-option))))))
       
       (read-location #'(lambda ()
			  (and repl-options
			       (let*
				   ((location (deno-repl-options-location repl-options))
				    (location-option (funcall read-string location)))
				 (and location-option (list "--location" location-option))))))
       
       (read-cached-only #'(lambda ()
			     (and repl-options
				  (let*
				      ((cached-only (deno-repl-options-cached-only repl-options))
				       (cached-only-option (funcall read-boolean cached-only)))
				    (and cached-only-option (list "--cached-only"))))))
       
       (read-compat #'(lambda ()
			(and repl-options
			     (let*
				 ((compat (deno-repl-options-compat repl-options))
				  (compat-option (funcall read-boolean compat)))
			       (and compat-option (list "--compat"))))))
       
       (read-help #'(lambda ()
		      (and repl-options
			   (let*
			       ((help (deno-repl-options-help repl-options))
				(help-option (funcall read-boolean help)))
			     (and help-option (list "--help"))))))
       
       (read-lock-write #'(lambda ()
			    (and repl-options
				 (let*
				     ((lock-write (deno-repl-options-lock-write repl-options))
				      (lock-write-option (funcall read-boolean lock-write)))
				   (and lock-write-option (list "--lock-write"))))))
       
       (read-no-remote #'(lambda ()
			   (and repl-options
				(let*
				    ((no-remote (deno-repl-options-no-remote repl-options))
				     (no-remote-option (funcall read-boolean no-remote)))
				  (and no-remote-option (list "--no-remote"))))))
       
       (read-quiet #'(lambda ()
		       (and repl-options
			    (let*
				((quiet (deno-repl-options-quiet repl-options))
				 (quiet-option (funcall read-boolean quiet)))
			      (and quiet-option (list "--quiet"))))))
       
       (read-unstable #'(lambda ()
			  (and repl-options
			       (let*
				   ((unstable (deno-repl-options-unstable repl-options))
				    (unstable-option (funcall read-boolean unstable)))
				 (and unstable-option (list "--unstable"))))))

       (read-seed #'(lambda ()
		      (and repl-options
			   (let*
			       ((seed (deno-repl-options-seed repl-options))
				(seed-option (funcall read-number seed)))
			     (and seed-option (list "--seed" seed-option)))))))
    
    (string-join
     (append (list deno-cli-path)
	     deno-cli-args
	     (funcall read-config)
	     (funcall read-log-level)
	     (funcall read-lock)
	     (funcall read-cert)
	     (funcall read-eval)
	     (funcall read-import-map)
	     (funcall read-location)
	     (funcall read-cached-only)
	     (funcall read-compat)
	     (funcall read-help)
	     (funcall read-lock-write)
	     (funcall read-no-remote)
	     (funcall read-quiet)
	     (funcall read-unstable)
	     (funcall read-seed))
     " ")))

(provide 'deno-repl-options)
